/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 - 2008 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/

package com.genia.toolbox.projects.toolbox_basics_project.spring.manager.impl;

import java.util.Arrays;

import org.springframework.security.Authentication;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.util.CollectionUtils;

import com.genia.toolbox.security.bean.Permission;
import com.genia.toolbox.basics.exception.BundledException;
import com.genia.toolbox.basics.manager.PermissionManager;
import com.genia.toolbox.web.gwt.form.server.spring.context.FormProviderContext;

/**
 * An implementation to handle authorization.
 */
public class PermissionManagerGWTFormImpl
    implements PermissionManager
{

  /**
   * the {@link FormProviderContext} to use.
   */
  private FormProviderContext formProviderContext;

  /**
   * the description of the permission that the current user must have to be
   * able to view the form which will be saved.
   */
  private Permission permissionViewCreateForm;

  /**
   * the description of the permission that the current user must have to be
   * able to view the form which will be updated.
   */
  private Permission permissionViewUpdateForm;

  /**
   * the description of the permission that the current user must have to be
   * able to save the form.
   */
  private Permission permissionCreateForm;

  /**
   * the description of the permission that the current user must have to be
   * able to update the form.
   */
  private Permission permissionUpdateForm;



  /**
   * returns wether an action is authorized.
   * 
   * @return wether an action is authorized
   * @throws BundledException
   *           if an error occured
   */
  public boolean isAuthorized()
      throws BundledException
  {

    switch (getFormProviderContext().getCalledMethod()) {

      case getForm:
        return isAuthorized(getPermissionViewCreateForm(), getPermissionViewUpdateForm());

      case getInitialValue:
        if (getFormProviderContext().getDataIdentifier().getIdentifier() == null && isAuthorized(getPermissionViewCreateForm())) {
          return true;
        }
        if (getFormProviderContext().getDataIdentifier().getIdentifier() != null && isAuthorized(getPermissionViewUpdateForm())) {
          return true;
        }
        return false;

      case saveForm:
        if (getFormProviderContext().getDataIdentifier().getIdentifier() == null && isAuthorized(getPermissionCreateForm())) {
          return true;
        }
        if (getFormProviderContext().getDataIdentifier().getIdentifier() != null && isAuthorized(getPermissionUpdateForm())) {
          return true;
        }
        return false;
      case getSuggestions:
        return (isAuthorized(getPermissionViewCreateForm(), getPermissionViewUpdateForm()));

      case getDisplayString:
        return (isAuthorized(getPermissionViewCreateForm(), getPermissionViewUpdateForm()));

    }
    return false;
  }



  /**
   * returns whether the current user has one of the given permissions.
   * 
   * @param permissions
   *          the permissions to check
   * @return whether the current user has one of the given permissions
   */
  private boolean isAuthorized(Permission... permissions)
  {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication == null) {
      return false;
    }
    GrantedAuthority[] authorities = authentication.getAuthorities();
    if (authorities == null) {
      return false;
    }
    return CollectionUtils.containsAny(Arrays.asList(authorities), Arrays.asList(permissions));
  }



  /**
   * getter for the formProviderContext property.
   * 
   * @return the formProviderContext
   */
  public FormProviderContext getFormProviderContext()
  {
    return formProviderContext;
  }



  /**
   * setter for the formProviderContext property.
   * 
   * @param formProviderContext
   *          the formProviderContext to set
   */
  public void setFormProviderContext(FormProviderContext formProviderContext)
  {
    this.formProviderContext = formProviderContext;
  }



  /**
   * getter for the permissionSaveForm property.
   * 
   * @return the permissionSaveForm
   */
  public Permission getPermissionCreateForm()
  {
    return permissionCreateForm;
  }



  /**
   * setter for the permissionSaveForm property.
   * 
   * @param permissionSaveForm
   *          the permissionSaveForm to set
   */
  public void setPermissionCreateForm(Permission permissionSaveForm)
  {
    this.permissionCreateForm = permissionSaveForm;
  }



  /**
   * getter for the permissionUpdateForm property.
   * 
   * @return the permissionUpdateForm
   */
  public Permission getPermissionUpdateForm()
  {
    return permissionUpdateForm;
  }



  /**
   * setter for the permissionUpdateForm property.
   * 
   * @param permissionUpdateForm
   *          the permissionUpdateForm to set
   */
  public void setPermissionUpdateForm(Permission permissionUpdateForm)
  {
    this.permissionUpdateForm = permissionUpdateForm;
  }



  /**
   * getter for the permissionViewSaveForm property.
   * 
   * @return the permissionViewSaveForm
   */
  public Permission getPermissionViewCreateForm()
  {
    return permissionViewCreateForm;
  }



  /**
   * setter for the permissionViewSaveForm property.
   * 
   * @param permissionViewSaveForm
   *          the permissionViewSaveForm to set
   */
  public void setPermissionViewCreateForm(Permission permissionViewSaveForm)
  {
    this.permissionViewCreateForm = permissionViewSaveForm;
  }



  /**
   * getter for the permissionViewUpdateForm property.
   * 
   * @return the permissionViewUpdateForm
   */
  public Permission getPermissionViewUpdateForm()
  {
    return permissionViewUpdateForm;
  }



  /**
   * setter for the permissionViewUpdateForm property.
   * 
   * @param permissionViewUpdateForm
   *          the permissionViewUpdateForm to set
   */
  public void setPermissionViewUpdateForm(Permission permissionViewUpdateForm)
  {
    this.permissionViewUpdateForm = permissionViewUpdateForm;
  }

}
